<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 2.0.17">
<title>Boost.ContainerHash</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
/* Uncomment the following line when using as a custom stylesheet */
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
a{background:none}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
b,strong{font-weight:bold}
abbr{font-size:.9em}
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
dfn{font-style:italic}
hr{height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
audio,video{display:inline-block}
audio:not([controls]){display:none;height:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type=checkbox],input[type=radio]{padding:0}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,::before,::after{box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:0}
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
table thead,table tfoot{background:#f7f8f7}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt{background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.center{margin-left:auto;margin-right:auto}
.stretch{width:100%}
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
.clearfix::after,.float-group::after{clear:both}
:not(pre).nobreak{word-wrap:normal}
:not(pre).nowrap{white-space:nowrap}
:not(pre).pre-wrap{white-space:pre-wrap}
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
pre>code{display:block}
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
em em{font-style:normal}
strong strong{font-weight:400}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menuref{color:#000}
.menuseq b:not(.caret),.menuref{font-weight:inherit}
.menuseq{word-spacing:-.02em}
.menuseq b.caret{font-size:1.25em;line-height:.8}
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
b.button::before{content:"[";padding:0 3px 0 2px}
b.button::after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
#content{margin-top:1.25em}
#content::before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span::before{content:"\00a0\2013\00a0"}
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber::after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
#content{margin-bottom:.625em}
.sect1{padding-bottom:.625em}
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
.sect1{padding-bottom:1.25em}}
.sect1:last-child{padding-bottom:0}
.sect1+.sect1{border-top:1px solid #e7e7e9}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
details{margin-left:1.25rem}
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
details>summary::-webkit-details-marker{display:none}
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
.listingblock>.content{position:relative}
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
.listingblock:hover code[data-lang]::before{display:block}
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.prettyprint{background:#f7f7f8}
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
pre.prettyprint li code[data-lang]::before{opacity:1}
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
table.linenotable td.code{padding-left:.75em}
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
.verseblock{margin:0 1em 1.25em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
p.tableblock:last-child{margin-bottom:0}
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all>*>tr>*{border-width:1px}
table.grid-cols>*>tr>*{border-width:0 1px}
table.grid-rows>*>tr>*{border-width:1px 0}
table.frame-all{border-width:1px}
table.frame-ends{border-width:1px 0}
table.frame-sides{border-width:0 1px}
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
ul.unstyled,ol.unstyled{margin-left:0}
li>p:empty:only-child::before{content:"";display:inline-block}
ul.checklist>li>p:first-child{margin-left:-1em}
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
ul.inline>li{margin-left:1.25em}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
td.hdlist2{word-wrap:anywhere}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
.colist td:not([class]):first-child img{max-width:none}
.colist td:not([class]):last-child{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
.imageblock.left{margin:.25em .625em 1.25em 0}
.imageblock.right{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background:#00fafa}
.black{color:#000}
.black-background{background:#000}
.blue{color:#0000bf}
.blue-background{background:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background:#fa00fa}
.gray{color:#606060}
.gray-background{background:#7d7d7d}
.green{color:#006000}
.green-background{background:#007d00}
.lime{color:#00bf00}
.lime-background{background:#00fa00}
.maroon{color:#600000}
.maroon-background{background:#7d0000}
.navy{color:#000060}
.navy-background{background:#00007d}
.olive{color:#606000}
.olive-background{background:#7d7d00}
.purple{color:#600060}
.purple-background{background:#7d007d}
.red{color:#bf0000}
.red-background{background:#fa0000}
.silver{color:#909090}
.silver-background{background:#bcbcbc}
.teal{color:#006060}
.teal-background{background:#007d7d}
.white{color:#bfbfbf}
.white-background{background:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background:#fafa00}
span.icon>.fa{cursor:default}
a span.icon>.fa{cursor:inherit}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]::after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt,summary{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@page{margin:1.25cm .75cm}
@media print{*{box-shadow:none!important;text-shadow:none!important}
html{font-size:80%}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]{border-bottom:1px dotted}
abbr[title]::after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#header,#content,#footnotes,#footer{max-width:none}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span::before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]::before{display:block}
#footer{padding:0 .9375em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
.sect1{padding:0!important}
.sect1+.sect1{border:0}
#footer{background:none}
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
</style>
<style>
pre.rouge table td { padding: 5px; }
pre.rouge table pre { margin: 0; }
pre.rouge .cm {
  color: #999988;
  font-style: italic;
}
pre.rouge .cp {
  color: #999999;
  font-weight: bold;
}
pre.rouge .c1 {
  color: #999988;
  font-style: italic;
}
pre.rouge .cs {
  color: #999999;
  font-weight: bold;
  font-style: italic;
}
pre.rouge .c, pre.rouge .ch, pre.rouge .cd, pre.rouge .cpf {
  color: #999988;
  font-style: italic;
}
pre.rouge .err {
  color: #a61717;
  background-color: #e3d2d2;
}
pre.rouge .gd {
  color: #000000;
  background-color: #ffdddd;
}
pre.rouge .ge {
  color: #000000;
  font-style: italic;
}
pre.rouge .gr {
  color: #aa0000;
}
pre.rouge .gh {
  color: #999999;
}
pre.rouge .gi {
  color: #000000;
  background-color: #ddffdd;
}
pre.rouge .go {
  color: #888888;
}
pre.rouge .gp {
  color: #555555;
}
pre.rouge .gs {
  font-weight: bold;
}
pre.rouge .gu {
  color: #aaaaaa;
}
pre.rouge .gt {
  color: #aa0000;
}
pre.rouge .kc {
  color: #000000;
  font-weight: bold;
}
pre.rouge .kd {
  color: #000000;
  font-weight: bold;
}
pre.rouge .kn {
  color: #000000;
  font-weight: bold;
}
pre.rouge .kp {
  color: #000000;
  font-weight: bold;
}
pre.rouge .kr {
  color: #000000;
  font-weight: bold;
}
pre.rouge .kt {
  color: #445588;
  font-weight: bold;
}
pre.rouge .k, pre.rouge .kv {
  color: #000000;
  font-weight: bold;
}
pre.rouge .mf {
  color: #009999;
}
pre.rouge .mh {
  color: #009999;
}
pre.rouge .il {
  color: #009999;
}
pre.rouge .mi {
  color: #009999;
}
pre.rouge .mo {
  color: #009999;
}
pre.rouge .m, pre.rouge .mb, pre.rouge .mx {
  color: #009999;
}
pre.rouge .sa {
  color: #000000;
  font-weight: bold;
}
pre.rouge .sb {
  color: #d14;
}
pre.rouge .sc {
  color: #d14;
}
pre.rouge .sd {
  color: #d14;
}
pre.rouge .s2 {
  color: #d14;
}
pre.rouge .se {
  color: #d14;
}
pre.rouge .sh {
  color: #d14;
}
pre.rouge .si {
  color: #d14;
}
pre.rouge .sx {
  color: #d14;
}
pre.rouge .sr {
  color: #009926;
}
pre.rouge .s1 {
  color: #d14;
}
pre.rouge .ss {
  color: #990073;
}
pre.rouge .s, pre.rouge .dl {
  color: #d14;
}
pre.rouge .na {
  color: #008080;
}
pre.rouge .bp {
  color: #999999;
}
pre.rouge .nb {
  color: #0086B3;
}
pre.rouge .nc {
  color: #445588;
  font-weight: bold;
}
pre.rouge .no {
  color: #008080;
}
pre.rouge .nd {
  color: #3c5d5d;
  font-weight: bold;
}
pre.rouge .ni {
  color: #800080;
}
pre.rouge .ne {
  color: #990000;
  font-weight: bold;
}
pre.rouge .nf, pre.rouge .fm {
  color: #990000;
  font-weight: bold;
}
pre.rouge .nl {
  color: #990000;
  font-weight: bold;
}
pre.rouge .nn {
  color: #555555;
}
pre.rouge .nt {
  color: #000080;
}
pre.rouge .vc {
  color: #008080;
}
pre.rouge .vg {
  color: #008080;
}
pre.rouge .vi {
  color: #008080;
}
pre.rouge .nv, pre.rouge .vm {
  color: #008080;
}
pre.rouge .ow {
  color: #000000;
  font-weight: bold;
}
pre.rouge .o {
  color: #000000;
  font-weight: bold;
}
pre.rouge .w {
  color: #bbbbbb;
}
pre.rouge {
  background-color: #f8f8f8;
}
</style>
</head>
<body class="article toc2 toc-left">
<div id="header">
<h1>Boost.ContainerHash</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#intro">Introduction</a></li>
<li><a href="#recent">Recent Changes</a>
<ul class="sectlevel2">
<li><a href="#recent_boost_1_84_0">Boost 1.84.0</a></li>
<li><a href="#recent_boost_1_82_0">Boost 1.82.0</a></li>
<li><a href="#recent_boost_1_81_0">Boost 1.81.0</a></li>
<li><a href="#recent_boost_1_78_0">Boost 1.78.0</a></li>
</ul>
</li>
<li><a href="#tutorial">Tutorial</a></li>
<li><a href="#user">Extending boost::hash for User Types</a></li>
<li><a href="#combine">Combining Hash Values</a></li>
<li><a href="#describe">Hashing User Types with Boost.Describe</a></li>
<li><a href="#reference">Reference</a>
<ul class="sectlevel2">
<li><a href="#ref_boostcontainer_hashhash_fwd_hpp">&lt;boost/container_hash/&#8203;hash_fwd.hpp&gt;</a></li>
<li><a href="#ref_boostcontainer_hashhash_hpp">&lt;boost/container_hash/&#8203;hash.hpp&gt;</a>
<ul class="sectlevel3">
<li><a href="#ref_hasht">hash&lt;T&gt;</a></li>
<li><a href="#ref_hash_combine">hash_combine</a></li>
<li><a href="#ref_hash_range">hash_range</a></li>
<li><a href="#ref_hash_unordered_range">hash_unordered_range</a></li>
<li><a href="#ref_hash_value">hash_value</a></li>
</ul>
</li>
<li><a href="#ref_boostcontainer_hashis_range_hpp">&lt;boost/container_hash/&#8203;is_range.hpp&gt;</a>
<ul class="sectlevel3">
<li><a href="#ref_is_ranget">is_range&lt;T&gt;</a></li>
</ul>
</li>
<li><a href="#ref_boostcontainer_hashis_contiguous_range_hpp">&lt;boost/container_hash/&#8203;is_contiguous_range.hpp&gt;</a>
<ul class="sectlevel3">
<li><a href="#ref_is_contiguous_ranget">is_contiguous_range&lt;T&gt;</a></li>
</ul>
</li>
<li><a href="#ref_boostcontainer_hashis_unordered_range_hpp">&lt;boost/container_hash/&#8203;is_unordered_range.hpp&gt;</a>
<ul class="sectlevel3">
<li><a href="#ref_is_unordered_ranget">is_unordered_range&lt;T&gt;</a></li>
</ul>
</li>
<li><a href="#ref_boostcontainer_hashis_described_class_hpp">&lt;boost/container_hash/&#8203;is_described_class.hpp&gt;</a>
<ul class="sectlevel3">
<li><a href="#ref_is_described_classt">is_described_class&lt;T&gt;</a></li>
</ul>
</li>
<li><a href="#ref_boostcontainer_hashis_tuple_like_hpp">&lt;boost/container_hash/&#8203;is_tuple_like.hpp&gt;</a>
<ul class="sectlevel3">
<li><a href="#ref_is_tuple_liket">is_tuple_like&lt;T&gt;</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#notes">Design and Implementation Notes</a>
<ul class="sectlevel2">
<li><a href="#notes_quality_of_the_hash_function">Quality of the Hash Function</a></li>
<li><a href="#notes_the_hash_value_customization_point">The hash_value Customization Point</a></li>
<li><a href="#notes_hash_value_stability">Hash Value Stability</a></li>
<li><a href="#notes_hash_combine">hash_combine</a></li>
<li><a href="#notes_hash_range">hash_range</a></li>
</ul>
</li>
<li><a href="#links">Links</a></li>
<li><a href="#thanks">Acknowledgements</a></li>
<li><a href="#changes">Change Log</a>
<ul class="sectlevel2">
<li><a href="#changes_boost_1_67_0">Boost 1.67.0</a></li>
<li><a href="#changes_boost_1_66_0">Boost 1.66.0</a></li>
<li><a href="#changes_boost_1_65_0">Boost 1.65.0</a></li>
</ul>
</li>
<li><a href="#copyright">Copyright and License</a></li>
</ul>
</div>
</div>
<div id="content">
<div class="sect1">
<h2 id="intro"><a class="link" href="#intro">Introduction</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p><code>boost::hash</code> is an enhanced implementation of the
<a href="https://en.wikipedia.org/wiki/Hash_function">hash function</a> object specified by
C&#43;&#43;11 as <code>std::hash</code>. It is the default hash function for
<a href="../../../unordered/index.html">Boost.Unordered</a>,
<a href="../../../intrusive/index.html">Boost.Intrusive</a>'s unordered associative
containers, <a href="../../../multi_index/index.html">Boost.MultiIndex</a>'s hash
indices, and <a href="../../../bimap/index.html">Boost.Bimap</a>'s <code>unordered_set_of</code>.</p>
</div>
<div class="paragraph">
<p>Out of the box, <code>boost::hash</code> supports</p>
</div>
<div class="ulist">
<ul>
<li>
<p>standard integral types (integers, character types, and <code>bool</code>);</p>
</li>
<li>
<p>standard floating point types (<code>float</code>, <code>double</code>, <code>long double</code>);</p>
</li>
<li>
<p>pointers (to objects and to functions, but not pointers to members)
and <code>nullptr</code>;</p>
</li>
<li>
<p>enumeration types;</p>
</li>
<li>
<p>C arrays;</p>
</li>
<li>
<p><code>std::complex</code>;</p>
</li>
<li>
<p>tuple-like types, such as <code>std::pair</code>, <code>std::tuple</code>, and user-defined
types that specialize <code>std::tuple_size</code> and provide <code>get&lt;I&gt;</code>;</p>
</li>
<li>
<p>sequence-like types, both standard and user-defined (sequence-like types
have <code>begin()</code> and <code>end()</code> member functions returning iterators);</p>
</li>
<li>
<p>unordered sequences, standard or user-defined (sequences for which the hash
value does not depend on the element order, such as <code>std::unordered_set</code> and
<code>std::unordered_map</code>);</p>
</li>
<li>
<p>described structs and classes&#8201;&#8212;&#8201;ones that have been annotated with the
<code>BOOST_DESCRIBE_STRUCT</code> or <code>BOOST_DESCRIBE_CLASS</code> macros from
<a href="../../../describe/index.html">Boost.Describe</a>;</p>
</li>
<li>
<p><code>std::unique_ptr</code>, <code>std::shared_ptr</code>;</p>
</li>
<li>
<p><code>std::type_index</code>;</p>
</li>
<li>
<p><code>std::error_code</code>, <code>std::error_condition</code>;</p>
</li>
<li>
<p><code>std::optional</code>;</p>
</li>
<li>
<p><code>std::variant</code>, <code>std::monostate</code>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p><code>boost::hash</code> is extensible; it&#8217;s possible for a user-defined type <code>X</code> to make
iself hashable via <code>boost::hash&lt;X&gt;</code> by defining an appropriate overload of the
function <code>hash_value</code>. Many, if not most, Boost types already contain the
necessary support.</p>
</div>
<div class="paragraph">
<p><code>boost::hash</code> meets the requirements for <code>std::hash</code> specified in the C&#43;&#43;11
standard, namely, that for two different input values their corresponding hash
values are either guaranteed to be distinct, or the probability of their being
the same (a hash collision) is small. Standard unordered containers, and the
hash-based Boost containers, are designed to work well with such hash functions.</p>
</div>
<div class="paragraph">
<p><code>boost::hash</code> does not meet the stronger requirements often placed on hash
functions in a more general context. In particular, the hash function is not
cryptographic, is not collision-resistant against a determined adversary, and
does not necessarily possess good "avalanche" properties; that is, small
(single bit) perturbations in the input do not necessarily result in large
(half bits changing) perturbations in the output.</p>
</div>
<div class="paragraph">
<p>In particular, <code>boost::hash</code> has traditionally been the identity function for
all integral types that fit into <code>std::size_t</code>, because this guarantees lack of
collisions and is as fast as possible.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="recent"><a class="link" href="#recent">Recent Changes</a></h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="recent_boost_1_84_0"><a class="link" href="#recent_boost_1_84_0">Boost 1.84.0</a></h3>
<div class="ulist">
<ul>
<li>
<p>C&#43;&#43;03 is no longer supported.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="recent_boost_1_82_0"><a class="link" href="#recent_boost_1_82_0">Boost 1.82.0</a></h3>
<div class="ulist">
<ul>
<li>
<p>Added an overload of <code>hash_value</code> for <code>std::nullptr_t</code>.</p>
</li>
<li>
<p>Added <code>is_tuple_like</code> and an overload of <code>hash_value</code> for
tuple-like types.</p>
</li>
<li>
<p>Changed string hashing to use
<a href="https://github.com/pdimov/mulxp_hash"><code>mulxp1_hash</code></a>,
improving both quality and speed. This changes the hash values
for string-like types (ranges of <code>char</code>, <code>signed char</code>,
<code>unsigned char</code>, <code>std::byte</code>, <code>char8_t</code>).</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="recent_boost_1_81_0"><a class="link" href="#recent_boost_1_81_0">Boost 1.81.0</a></h3>
<div class="paragraph">
<p>Major update.</p>
</div>
<div class="ulist">
<ul>
<li>
<p>The specializations of <code>boost::hash</code> have been removed; it now
always calls <code>hash_value</code>.</p>
</li>
<li>
<p>Support for <code>BOOST_HASH_NO_EXTENSIONS</code> has been removed. The
extensions are always enabled.</p>
</li>
<li>
<p>All standard containers are now supported. This includes
<code>std::forward_list</code> and the unordered associative containers.</p>
</li>
<li>
<p>User-defined containers (types that have <code>begin()</code> and <code>end()</code>
member functions that return iterators) are now supported out
of the box.</p>
</li>
<li>
<p>Described structs and classes (those annotated with
<code>BOOST_DESCRIBE_STRUCT</code> or <code>BOOST_DESCRIBE_CLASS</code>) are now
supported out of the box.</p>
</li>
<li>
<p><code>hash_combine</code> has been improved. This changes the hash values
of composite (container and tuple) types and of scalar types
bigger than <code>size_t</code>.</p>
</li>
<li>
<p>The performance (and quality, as a result of the above change)
of string hashing has been improved. <code>boost::hash</code> for strings
now passes SMHasher in 64 bit mode.</p>
</li>
<li>
<p>The documentation has been substantially revised to reflect
the changes.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="recent_boost_1_78_0"><a class="link" href="#recent_boost_1_78_0">Boost 1.78.0</a></h3>
<div class="ulist">
<ul>
<li>
<p>Fixed <code>hash_combine</code> so that its behavior no longer depends
on whether <code>size_t</code> is the exact same type as <code>boost::uint64_t</code>
(which wasn&#8217;t the case on macOS). This changes the hash values
of composite (container and tuple) types on macOS.</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="tutorial"><a class="link" href="#tutorial">Tutorial</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>When using a Boost container such as
<a href="../../../unordered/index.html">Boost.Unordered</a>, you don&#8217;t need to do
anything to use <code>boost::hash</code> as it&#8217;s the default. To find out how to use
a user-defined type, read the <a href="#user">section on extending boost::hash
for user types</a>.</p>
</div>
<div class="paragraph">
<p>If you wish to use <code>boost::hash</code> with the standard unordered associative
containers, pass it as a template parameter:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="n">unordered_multiset</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&gt;</span>
        <span class="n">set_of_ints</span><span class="p">;</span>

<span class="n">std</span><span class="o">::</span><span class="n">unordered_set</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="o">&gt;</span>
        <span class="n">set_of_pairs</span><span class="p">;</span>

<span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">map_int_to_string</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>To use <code>boost::hash</code> directly, create an instance and call it as a function:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="cp">#include</span> <span class="cpf">&lt;boost/container_hash/hash.hpp&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">string_hash</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">h</span> <span class="o">=</span> <span class="n">string_hash</span><span class="p">(</span><span class="s">"Hash me"</span><span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>or alternatively:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="cp">#include</span> <span class="cpf">&lt;boost/container_hash/hash.hpp&gt;</span><span class="cp">
</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">h</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">()(</span><span class="s">"Hash me"</span><span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>For an example of generic use, here is a function to generate a vector
containing the hashes of the elements of a container:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span> <span class="nc">Container</span><span class="p">&gt;</span>
<span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">get_hashes</span><span class="p">(</span><span class="n">Container</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">x</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&gt;</span> <span class="n">hashes</span><span class="p">;</span>
    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">x</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">x</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">back_inserter</span><span class="p">(</span><span class="n">hashes</span><span class="p">),</span>
        <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">Container</span><span class="o">::</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">());</span>

    <span class="k">return</span> <span class="n">hashes</span><span class="p">;</span>
<span class="p">}</span></code></pre>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="user"><a class="link" href="#user">Extending boost::hash for User Types</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p><code>boost::hash</code> is implemented by calling the function <code>hash_value</code>. The
namespace isn&#8217;t specified so that it can detect overloads via argument
dependant lookup. So if there is a free function <code>hash_value</code> in the same
namespace as a user type, it will get called.</p>
</div>
<div class="paragraph">
<p>If you have a structure <code>library::book</code>, where each book is uniquely defined
by its member <code>id</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">library</span>
<span class="p">{</span>
    <span class="k">struct</span> <span class="nc">book</span>
    <span class="p">{</span>
        <span class="kt">int</span> <span class="n">id</span><span class="p">;</span>
        <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">author</span><span class="p">;</span>
        <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">title</span><span class="p">;</span>

        <span class="c1">// ....</span>
    <span class="p">};</span>

    <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">book</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">book</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">b</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="k">return</span> <span class="n">a</span><span class="p">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">b</span><span class="p">.</span><span class="n">id</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Then all you would need to do is write the function <code>library::hash_value</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">library</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span><span class="n">book</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">b</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">hasher</span><span class="p">;</span>
        <span class="k">return</span> <span class="n">hasher</span><span class="p">(</span><span class="n">b</span><span class="p">.</span><span class="n">id</span><span class="p">);</span>
    <span class="p">}</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>And you can now use <code>boost::hash</code> with book:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">library</span><span class="o">::</span><span class="n">book</span> <span class="nf">knife</span><span class="p">(</span><span class="mi">3458</span><span class="p">,</span> <span class="s">"Zane Grey"</span><span class="p">,</span> <span class="s">"The Hash Knife Outfit"</span><span class="p">);</span>
<span class="n">library</span><span class="o">::</span><span class="n">book</span> <span class="nf">dandelion</span><span class="p">(</span><span class="mi">1354</span><span class="p">,</span> <span class="s">"Paul J. Shanley"</span><span class="p">,</span>
    <span class="s">"Hash &amp; Dandelion Greens"</span><span class="p">);</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">library</span><span class="o">::</span><span class="n">book</span><span class="o">&gt;</span> <span class="n">book_hasher</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">knife_hash_value</span> <span class="o">=</span> <span class="n">book_hasher</span><span class="p">(</span><span class="n">knife</span><span class="p">);</span>

<span class="c1">// If std::unordered_set is available:</span>
<span class="n">std</span><span class="o">::</span><span class="n">unordered_set</span><span class="o">&lt;</span><span class="n">library</span><span class="o">::</span><span class="n">book</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">library</span><span class="o">::</span><span class="n">book</span><span class="o">&gt;</span> <span class="o">&gt;</span> <span class="n">books</span><span class="p">;</span>
<span class="n">books</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">knife</span><span class="p">);</span>
<span class="n">books</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">library</span><span class="o">::</span><span class="n">book</span><span class="p">(</span><span class="mi">2443</span><span class="p">,</span> <span class="s">"Lindgren, Torgny"</span><span class="p">,</span> <span class="s">"Hash"</span><span class="p">));</span>
<span class="n">books</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">library</span><span class="o">::</span><span class="n">book</span><span class="p">(</span><span class="mi">1953</span><span class="p">,</span> <span class="s">"Snyder, Bernadette M."</span><span class="p">,</span>
    <span class="s">"Heavenly Hash: A Tasty Mix of a Mother's Meditations"</span><span class="p">));</span>

<span class="n">assert</span><span class="p">(</span><span class="n">books</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">knife</span><span class="p">)</span> <span class="o">!=</span> <span class="n">books</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
<span class="n">assert</span><span class="p">(</span><span class="n">books</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">dandelion</span><span class="p">)</span> <span class="o">==</span> <span class="n">books</span><span class="p">.</span><span class="n">end</span><span class="p">());</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>The full example can be found in
<a href="../../examples/books.hpp">examples/books.hpp</a> and
<a href="../../examples/books.cpp">examples/books.cpp</a>.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
When writing a hash function, first look at how the equality function
works. Objects that are equal must generate the same hash value. When objects
are not equal they should generate different hash values. In this object
equality was based just on <code>id</code> so the hash function only hashes <code>id</code>. If it
was based on the object&#8217;s name and author then the hash function should take
them into account (how to do this is discussed in the next section).
</td>
</tr>
</table>
</div>
</div>
</div>
<div class="sect1">
<h2 id="combine"><a class="link" href="#combine">Combining Hash Values</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Say you have a point class, representing a two dimensional location:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">class</span> <span class="nc">point</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">y</span><span class="p">;</span>

<span class="nl">public:</span>

    <span class="n">point</span><span class="p">()</span> <span class="o">:</span> <span class="n">x</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>
    <span class="n">point</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="o">:</span> <span class="n">x</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="p">{}</span>

    <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="n">point</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span>
    <span class="p">{</span>
        <span class="k">return</span> <span class="n">x</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">x</span> <span class="o">&amp;&amp;</span> <span class="n">y</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
    <span class="p">}</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>and you wish to use it as the key for an <code>unordered_map</code>. You need to
customise the hash for this structure. To do this we need to combine the
hash values for <code>x</code> and <code>y</code>. The function <code>boost::hash_combine</code> is supplied
for this purpose:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">class</span> <span class="nc">point</span>
<span class="p">{</span>
    <span class="p">...</span>

    <span class="k">friend</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span><span class="n">point</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">)</span>
    <span class="p">{</span>
        <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

        <span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">x</span><span class="p">);</span>
        <span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">y</span><span class="p">);</span>

        <span class="k">return</span> <span class="n">seed</span><span class="p">;</span>
    <span class="p">}</span>

    <span class="p">...</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Calls to <code>hash_combine</code> incrementally build the hash from the different
members of <code>point</code>, it can be repeatedly called for any number of elements.
It calls <code>hash_value</code> on the supplied element, and combines it with the seed.</p>
</div>
<div class="paragraph">
<p>Full code for this example is at <a href="../../examples/point.cpp">examples/point.cpp</a>.</p>
</div>
<div class="paragraph">
<p>Note that when using <code>boost::hash_combine</code> the order of the calls matters.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>and</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span><span class="n">seed</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>result in a different values in <code>seed</code>.</p>
</div>
<div class="paragraph">
<p>To calculate the hash of an iterator range you can use <code>boost::hash_range</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">some_strings</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash_range</span><span class="p">(</span><span class="n">some_strings</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">some_strings</span><span class="p">.</span><span class="n">end</span><span class="p">());</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Since <code>hash_range</code> works by repeatedly invoking <code>hash_combine</code> on the elements
of the range, the hash value will also be dependent on the element order.</p>
</div>
<div class="paragraph">
<p>If you are calculating a hash value for a range where the order of the data
doesn&#8217;t matter, such as <code>unordered_set</code>, you can use
<code>boost::hash_unordered_range</code> instead.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="n">unordered_set</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">set</span><span class="p">;</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash</span> <span class="o">=</span> <span class="n">boost</span><span class="o">::</span><span class="n">hash_unordered_range</span><span class="p">(</span><span class="n">set</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">set</span><span class="p">.</span><span class="n">end</span><span class="p">());</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>When writing template classes, you might not want to include the main
<code>hash.hpp</code> header as it&#8217;s quite an expensive include that brings in a lot of
other headers, so instead you can include the
<code>&lt;boost/container_hash/hash_fwd.hpp&gt;</code> header which forward declares
<code>boost::hash</code>, <code>boost::hash_combine</code>, <code>boost::hash_range</code>, and
<code>boost::hash_unordered_range</code>. You&#8217;ll need to include the main header before
instantiating <code>boost::hash</code>. When using a container that uses <code>boost::hash</code> it
should do that for you, so your type will work fine with the Boost hash
containers. There&#8217;s an example of this in
<a href="../../examples/template.hpp">examples/template.hpp</a> and
<a href="../../examples/template.cpp">examples/template.cpp</a>.</p>
</div>
<div class="paragraph">
<p>To avoid including even <code>hash_fwd.hpp</code> - which still requires the contents
of Boost.ContainerHash to be physically present - you are allowed to copy the
declarations from <code>hash_fwd.hpp</code> (and only those) directly into your own
header. This is a special exception guaranteed by the library; in general,
you can&#8217;t declare library functions, Boost or otherwise, without risk of
breakage in a subsequent release.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="describe"><a class="link" href="#describe">Hashing User Types with Boost.Describe</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>Let&#8217;s look at our <code>point</code> class again:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">class</span> <span class="nc">point</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">y</span><span class="p">;</span>

<span class="nl">public:</span>

    <span class="n">point</span><span class="p">()</span> <span class="o">:</span> <span class="n">x</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>
    <span class="n">point</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="o">:</span> <span class="n">x</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="p">{}</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>If you&#8217;re using C&#43;&#43;14 or above, a much easier way to add
support for <code>boost::hash</code> to <code>point</code> is by using
<a href="../../../describe/index.html">Boost.Describe</a> (and
get an automatic definition of <code>operator==</code> for free):</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="cp">#include</span> <span class="cpf">&lt;boost/describe/class.hpp&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;boost/describe/operators.hpp&gt;</span><span class="cp">
</span>
<span class="k">class</span> <span class="nc">point</span>
<span class="p">{</span>
    <span class="kt">int</span> <span class="n">x</span><span class="p">;</span>
    <span class="kt">int</span> <span class="n">y</span><span class="p">;</span>

    <span class="n">BOOST_DESCRIBE_CLASS</span><span class="p">(</span><span class="n">point</span><span class="p">,</span> <span class="p">(),</span> <span class="p">(),</span> <span class="p">(),</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>

<span class="nl">public:</span>

    <span class="n">point</span><span class="p">()</span> <span class="o">:</span> <span class="n">x</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>
    <span class="n">point</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">,</span> <span class="kt">int</span> <span class="n">y</span><span class="p">)</span> <span class="o">:</span> <span class="n">x</span><span class="p">(</span><span class="n">x</span><span class="p">),</span> <span class="n">y</span><span class="p">(</span><span class="n">y</span><span class="p">)</span> <span class="p">{}</span>
<span class="p">};</span>

<span class="k">using</span> <span class="n">boost</span><span class="o">::</span><span class="n">describe</span><span class="o">::</span><span class="n">operators</span><span class="o">::</span><span class="k">operator</span><span class="o">==</span><span class="p">;</span>
<span class="k">using</span> <span class="n">boost</span><span class="o">::</span><span class="n">describe</span><span class="o">::</span><span class="n">operators</span><span class="o">::</span><span class="k">operator</span><span class="o">!=</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>(Full code for this example is at
<a href="../../examples/point2.cpp">examples/point2.cpp</a>.)</p>
</div>
<div class="paragraph">
<p>Since the <code>point</code> class has been annotated with <code>BOOST_DESCRIBE_CLASS</code>,
the library can enumerate its members (and base classes) and automatically
synthesize the appropriate <code>hash_value</code> overload for it, without us needing
to do so.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="reference"><a class="link" href="#reference">Reference</a></h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="ref_boostcontainer_hashhash_fwd_hpp"><a class="link" href="#ref_boostcontainer_hashhash_fwd_hpp">&lt;boost/container_hash/&#8203;hash_fwd.hpp&gt;</a></h3>
<div class="paragraph">
<p>This header contains forward declarations for the library primitives.
These declarations are guaranteed to be relatively stable, that is,
best effort will be expended on their not changing from release to
release, allowing their verbatim copy into user headers that do not
wish to physically depend on Boost.ContainerHash.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">namespace</span> <span class="n">container_hash</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_range</span><span class="p">;</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_contiguous_range</span><span class="p">;</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_unordered_range</span><span class="p">;</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_described_class</span><span class="p">;</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_tuple_like</span><span class="p">;</span>

<span class="p">}</span> <span class="c1">// namespace container_hash</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">hash</span><span class="p">;</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="n">hash_combine</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="n">hash_range</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_range</span><span class="p">(</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="n">hash_unordered_range</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_unordered_range</span><span class="p">(</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boostcontainer_hashhash_hpp"><a class="link" href="#ref_boostcontainer_hashhash_hpp">&lt;boost/container_hash/&#8203;hash.hpp&gt;</a></h3>
<div class="paragraph">
<p>Defines <code>boost::hash</code>, and helper functions.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">hash</span><span class="p">;</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="n">hash_combine</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="n">hash_range</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_range</span><span class="p">(</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="n">hash_unordered_range</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_unordered_range</span><span class="p">(</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span>

<span class="c1">// Enabled only when T is an integral type</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when T is an enumeration type</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when T is a floating point type</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span><span class="o">*</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">N</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">v</span><span class="p">)[</span><span class="n">N</span><span class="p">]</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">complex</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">A</span><span class="p">,</span> <span class="k">class</span> <span class="nc">B</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when container_hash::is_tuple_like&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when container_hash::is_range&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when container_hash::is_contiguous_range&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when container_hash::is_unordered_range&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="c1">// Enabled only when container_hash::is_described_class&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="k">class</span> <span class="nc">D</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">D</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">type_index</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">error_condition</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">monostate</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span><span class="o">...</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">T</span><span class="p">...</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="ref_hasht"><a class="link" href="#ref_hasht">hash&lt;T&gt;</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">hash</span>
<span class="p">{</span>
    <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="k">operator</span><span class="p">()(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">)</span> <span class="k">const</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="sect4">
<h5 id="ref_operator"><a class="link" href="#ref_operator">operator()</a></h5>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="k">operator</span><span class="p">()(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">)</span> <span class="k">const</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>hash_value(v)</code>.</p>
</dd>
<dt class="hdlist1">Throws: </dt>
<dd>
<p>Only throws if <code>hash_value(v)</code> throws.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>The call to <code>hash_value</code> is unqualified, so that user-supplied
overloads will be found via argument dependent lookup.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect3">
<h4 id="ref_hash_combine"><a class="link" href="#ref_hash_combine">hash_combine</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="nf">hash_combine</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Called repeatedly to incrementally create a hash value from several variables.</p>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<p>Updates <code>seed</code> with a new hash value generated by
deterministically combining it with the result of <code>boost::hash&lt;T&gt;()(v)</code>.</p>
</dd>
<dt class="hdlist1">Throws: </dt>
<dd>
<p>Only throws if <code>boost::hash&lt;T&gt;()(v)</code> throws. On exception,
<code>seed</code> is not updated.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<div class="openblock">
<div class="content">
<div class="paragraph">
<p>Equivalent to <code>seed = combine(seed, boost::hash&lt;T&gt;()(v))</code>,
where <code>combine(s, v)</code> is a mixing function that takes two arguments of
type <code>std::size_t</code> and returns <code>std::size_t</code>, with the following desirable
properties:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>For a constant <code>s</code>, when <code>v</code> takes all possible <code>size_t</code> values,
<code>combine(s, v)</code> should also take all possible <code>size_t</code> values, producing
a sequence that is close to random; that is, it should be a random
permutation.</p>
<div class="paragraph">
<p>This guarantees that for a given <code>seed</code>, <code>combine</code> does not introduce
hash collisions when none were produced by <code>boost::hash&lt;T&gt;(v)</code>; that is,
it does not lose information from the input. It also implies that
<code>combine(s, v)</code>, as a function of <code>v</code>, has good avalanche properties;
that is, small (e.g. single bit) perturbations in the input <code>v</code> lead to
large perturbations in the return value (half of the output bits changing,
on average).</p>
</div>
</li>
<li>
<p>For two different seeds <code>s1</code> and <code>s2</code>, <code>combine(s1, v)</code> and
<code>combine(s2, v)</code>, treated as functions of <code>v</code>, should produce two
different random permutations.</p>
</li>
<li>
<p><code>combine(0, 0)</code> should not be 0. Since a common initial value of <code>seed</code>
is zero, <code>combine(0, 0) == 0</code> would imply that applying <code>hash_combine</code> on
any sequence of zeroes, regardless of length, will produce zero. This is
undesirable, as it would lead to e.g. <code>std::vector&lt;int&gt;()</code> and
<code>std::vector&lt;int&gt;(4)</code> to have the same hash value.</p>
</li>
</ol>
</div>
<div class="paragraph">
<p>The current implementation uses the function <code>mix(s + 0x9e3779b9 + v)</code> as
<code>combine(s, v)</code>, where <code>mix(x)</code> is a high quality mixing function that is a
bijection over the <code>std::size_t</code> values, of the form</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">k1</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="n">m1</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">k2</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="n">m2</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">k3</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>where the constants <code>k1</code>, <code>k2</code>, <code>k3</code>, <code>m1</code>, <code>m2</code> are suitably chosen.</p>
</div>
<div class="paragraph">
<p>Note that <code>mix(0)</code> is 0. This is why we add the arbitrary constant
<code>0x9e3779b9</code> to meet the third requirement above.</p>
</div>
</div>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="ref_hash_range"><a class="link" href="#ref_hash_range">hash_range</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="nf">hash_range</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="openblock">
<div class="content">
<div class="paragraph">
<p>When <code>typename std::iterator_traits&lt;It&gt;::value_type</code> is not <code>char</code>, <code>signed char</code>,
<code>unsigned char</code>, <code>std::byte</code>, or <code>char8_t</code>,</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">for</span><span class="p">(</span> <span class="p">;</span> <span class="n">first</span> <span class="o">!=</span> <span class="n">last</span><span class="p">;</span> <span class="o">++</span><span class="n">first</span> <span class="p">)</span>
<span class="p">{</span>
    <span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="o">*</span><span class="n">first</span> <span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Otherwise, bytes from <code>[first, last)</code> are coalesced and hashed in an
unspecified manner. This is done in order to improve performance when hashing
strings.</p>
</div>
</div>
</div>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>For chars, the current implementation uses
<a href="https://github.com/pdimov/mulxp_hash"><code>mulxp1_hash</code></a> when <code>std::size_t</code> is
64 bit, and <code>mulxp1_hash32</code> when it&#8217;s 32 bit.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_range</span><span class="p">(</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_range</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">first</span><span class="p">,</span> <span class="n">last</span> <span class="p">);</span>
<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="ref_hash_unordered_range"><a class="link" href="#ref_hash_unordered_range">hash_unordered_range</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="kt">void</span> <span class="nf">hash_unordered_range</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span><span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<p>Updates <code>seed</code> with the values of
<code>boost::hash&lt;typename std::iterator_traits&lt;It&gt;::value_type&gt;()(*i)</code>
for each <code>i</code> in <code>[first, last)</code>, such that the order of elements does
not affect the final result.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">It</span><span class="p">&gt;</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_unordered_range</span><span class="p">(</span> <span class="n">It</span> <span class="n">first</span><span class="p">,</span> <span class="n">It</span> <span class="n">last</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_unordered_range</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">first</span><span class="p">,</span> <span class="n">last</span> <span class="p">);</span>
<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
</dd>
</dl>
</div>
</div>
<div class="sect3">
<h4 id="ref_hash_value"><a class="link" href="#ref_hash_value">hash_value</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when T is an integral type</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p>When the value of <code>v</code> fits into <code>std::size_t</code>, when <code>T</code> is an unsigned type,
or into <code>ssize_t</code>, when <code>T</code> is a signed type, <code>static_cast&lt;std::size_t&gt;(v)</code>.</p>
<div class="paragraph">
<p>Otherwise, an unspecified value obtained by mixing the value bits of <code>v</code>.</p>
</div>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when T is an enumeration type</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>static_cast&lt;std::size_t&gt;(v)</code>.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p><code>hash_value(std::to_underlying(v))</code> would be better, but C&#43;&#43;03
compatibility mandates the current implementation.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when T is a floating point type</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p>An unspecified value obtained by mixing the value bits of <code>v</code>.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>When <code>sizeof(v) &lt;= sizeof(std::size_t)</code>, the bits of <code>v</code> are returned
as-is (except in the case of -0.0, which is treated as +0.0).</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span><span class="o">*</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p>An unspecified value derived from <code>reinterpret_cast&lt;std::uintptr_t&gt;(v)</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">N</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span> <span class="p">(</span><span class="o">&amp;</span><span class="n">v</span><span class="p">)[</span><span class="n">N</span><span class="p">]</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>boost::hash_range( v, v + N )</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">complex</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p>An unspecified value derived from <code>boost::hash&lt;T&gt;()(v.real())</code> and
<code>boost::hash&lt;T&gt;()(v.imag())</code> such that, if <code>v.imag() == 0</code>, the value
is equal to <code>boost::hash&lt;T&gt;()(v.real())</code>.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>A more straightforward implementation would just have used <code>hash_combine</code>
on <code>v.real()</code> and <code>v.imag()</code>, but the historical guarantee that real-valued
complex numbers should match the hash value of their real part precludes it.</p>
<div class="paragraph">
<p>This guarantee may be dropped in a future release, as it&#8217;s of questionable
utility.</p>
</div>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">A</span><span class="p">,</span> <span class="k">class</span> <span class="nc">B</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">v</span><span class="p">.</span><span class="n">first</span> <span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">v</span><span class="p">.</span><span class="n">second</span> <span class="p">);</span>

<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when container_hash::is_tuple_like&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="p">;</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="p">);</span>
<span class="c1">// ...</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">get</span><span class="o">&lt;</span><span class="n">N</span><span class="o">-</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="p">);</span>

<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>where <code>N</code> is <code>std::tuple_size&lt;T&gt;::value</code>.</p>
</div>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>This overload is only enabled when
<code>container_hash::is_range&lt;T&gt;::value</code> is <code>false</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when container_hash::is_range&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>boost::hash_range( v.begin(), v.end() )</code>.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>This overload is only enabled when
<code>container_hash::is_contiguous_range&lt;T&gt;::value</code> and
<code>container_hash::is_unordered_range&lt;T&gt;::value</code> are both <code>false</code>.</p>
<div class="paragraph">
<p>It handles all standard containers that aren&#8217;t contiguous or unordered, such
as <code>std::deque</code>, <code>std::list</code>, <code>std::set</code>, <code>std::map</code>.</p>
</div>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when container_hash::is_contiguous_range&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>boost::hash_range( v.data(), v.data() + v.size() )</code>.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>This overload handles all standard contiguous containers, such as
<code>std::string</code>, <code>std::vector</code>, <code>std::array</code>, <code>std::string_view</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when container_hash::is_unordered_range&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>boost::hash_unordered_range( v.begin(), v.end() )</code>.</p>
</dd>
<dt class="hdlist1">Remarks: </dt>
<dd>
<p>This overload handles the standard unordered containers, such as
<code>std::unordered_set</code> and <code>std::unordered_map</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="c1">// Enabled only when container_hash::is_described_class&lt;T&gt;::value is true</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">T</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">b1</span> <span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">b2</span> <span class="p">);</span>
<span class="c1">// ...</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">bM</span> <span class="p">);</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">m1</span> <span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">m2</span> <span class="p">);</span>
<span class="c1">// ...</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">mN</span> <span class="p">);</span>

<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>where <code>bi</code> are the bases of <code>v</code> and <code>mi</code> are its members.</p>
</div>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">,</span> <span class="k">class</span> <span class="nc">D</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">D</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>boost::hash&lt;T*&gt;( v.get() )</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">type_index</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p><code>v.hash_code()</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span>
<span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">error_condition</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">v</span><span class="p">.</span><span class="n">value</span><span class="p">()</span> <span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">v</span><span class="p">.</span><span class="n">category</span><span class="p">()</span> <span class="p">);</span>

<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p>For a disengaged <code>v</code>, an unspecified constant value; otherwise,
<code>boost::hash&lt;T&gt;()( *v )</code>.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">monostate</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Returns: </dt>
<dd>
<p>An unspecified constant value.</p>
</dd>
</dl>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span><span class="o">...</span> <span class="nc">T</span><span class="p">&gt;</span>
  <span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="nf">hash_value</span><span class="p">(</span> <span class="n">std</span><span class="o">::</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">T</span><span class="p">...</span><span class="o">&gt;</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">v</span> <span class="p">);</span></code></pre>
</div>
</div>
<div class="dlist">
<dl>
<dt class="hdlist1">Effects: </dt>
<dd>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">std</span><span class="o">::</span><span class="kt">size_t</span> <span class="n">seed</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>

<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">v</span><span class="p">.</span><span class="n">index</span><span class="p">()</span> <span class="p">);</span>
<span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="n">x</span> <span class="p">);</span>

<span class="k">return</span> <span class="n">seed</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>where <code>x</code> is the currently contained value in <code>v</code>.</p>
</div>
</dd>
<dt class="hdlist1">Throws: </dt>
<dd>
<p><code>std::bad_variant_access</code> when <code>v.valueless_by_exception()</code> is <code>true</code>.</p>
</dd>
</dl>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boostcontainer_hashis_range_hpp"><a class="link" href="#ref_boostcontainer_hashis_range_hpp">&lt;boost/container_hash/&#8203;is_range.hpp&gt;</a></h3>
<div class="paragraph">
<p>Defines the trait <code>boost::container_hash::is_range</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">namespace</span> <span class="n">container_hash</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_range</span><span class="p">;</span>

<span class="p">}</span> <span class="c1">// namespace container_hash</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="ref_is_ranget"><a class="link" href="#ref_is_ranget">is_range&lt;T&gt;</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_range</span>
<span class="p">{</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="cm">/* see below */</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>is_range&lt;T&gt;::value</code> is <code>true</code> when, for a const value <code>x</code> of type
<code>T</code>, <code>x.begin()</code> and <code>x.end()</code> return iterators of the same type
<code>It</code> (such that <code>std::iterator_traits&lt;It&gt;</code> is a valid specialization.)</p>
</div>
<div class="paragraph">
<p>Users are allowed to specialize <code>is_range</code> for their types if the
default behavior does not deduce the correct value.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boostcontainer_hashis_contiguous_range_hpp"><a class="link" href="#ref_boostcontainer_hashis_contiguous_range_hpp">&lt;boost/container_hash/&#8203;is_contiguous_range.hpp&gt;</a></h3>
<div class="paragraph">
<p>Defines the trait <code>boost::container_hash::is_contiguous_range</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">namespace</span> <span class="n">container_hash</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_contiguous_range</span><span class="p">;</span>

<span class="p">}</span> <span class="c1">// namespace container_hash</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="ref_is_contiguous_ranget"><a class="link" href="#ref_is_contiguous_ranget">is_contiguous_range&lt;T&gt;</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_contiguous_range</span>
<span class="p">{</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="cm">/* see below */</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>is_contiguous_range&lt;T&gt;::value</code> is <code>true</code> when <code>is_range&lt;T&gt;::value</code> is
<code>true</code> and when, for a const value <code>x</code> of type <code>T</code>, <code>x.data()</code> returns
a pointer to a type that matches the <code>value_type</code> of the iterator returned
by <code>x.begin()</code> and <code>x.end()</code>, and <code>x.size()</code> returns a value of an integral
type.</p>
</div>
<div class="paragraph">
<p>Users are allowed to specialize <code>is_contiguous_range</code> for their types
if the default behavior does not deduce the correct value.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boostcontainer_hashis_unordered_range_hpp"><a class="link" href="#ref_boostcontainer_hashis_unordered_range_hpp">&lt;boost/container_hash/&#8203;is_unordered_range.hpp&gt;</a></h3>
<div class="paragraph">
<p>Defines the trait <code>boost::container_hash::is_unordered_range</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">namespace</span> <span class="n">container_hash</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_unordered_range</span><span class="p">;</span>

<span class="p">}</span> <span class="c1">// namespace container_hash</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="ref_is_unordered_ranget"><a class="link" href="#ref_is_unordered_ranget">is_unordered_range&lt;T&gt;</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_unordered_range</span>
<span class="p">{</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="cm">/* see below */</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>is_unordered_range&lt;T&gt;::value</code> is <code>true</code> when <code>is_range&lt;T&gt;::value</code> is
<code>true</code> and when <code>T::hasher</code> is a valid type.</p>
</div>
<div class="paragraph">
<p>Users are allowed to specialize <code>is_unordered_range</code> for their types
if the default behavior does not deduce the correct value.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boostcontainer_hashis_described_class_hpp"><a class="link" href="#ref_boostcontainer_hashis_described_class_hpp">&lt;boost/container_hash/&#8203;is_described_class.hpp&gt;</a></h3>
<div class="paragraph">
<p>Defines the trait <code>boost::container_hash::is_described_class</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">namespace</span> <span class="n">container_hash</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_described_class</span><span class="p">;</span>

<span class="p">}</span> <span class="c1">// namespace container_hash</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="ref_is_described_classt"><a class="link" href="#ref_is_described_classt">is_described_class&lt;T&gt;</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_described_class</span>
<span class="p">{</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="cm">/* see below */</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>is_described_class&lt;T&gt;::value</code> is <code>true</code> when
<code>boost::describe::has_describe_bases&lt;T&gt;::value</code> is <code>true</code>,
<code>boost::describe::has_describe_members&lt;T&gt;::value</code> is <code>true</code>, and
<code>T</code> is not a union.</p>
</div>
<div class="paragraph">
<p>Users are allowed to specialize <code>is_described_class</code> for their types
if the default behavior does not deduce the correct value.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="ref_boostcontainer_hashis_tuple_like_hpp"><a class="link" href="#ref_boostcontainer_hashis_tuple_like_hpp">&lt;boost/container_hash/&#8203;is_tuple_like.hpp&gt;</a></h3>
<div class="paragraph">
<p>Defines the trait <code>boost::container_hash::is_tuple_like</code>.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">namespace</span> <span class="n">boost</span>
<span class="p">{</span>

<span class="k">namespace</span> <span class="n">container_hash</span>
<span class="p">{</span>

<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_tuple_like</span><span class="p">;</span>

<span class="p">}</span> <span class="c1">// namespace container_hash</span>

<span class="p">}</span> <span class="c1">// namespace boost</span></code></pre>
</div>
</div>
<div class="sect3">
<h4 id="ref_is_tuple_liket"><a class="link" href="#ref_is_tuple_liket">is_tuple_like&lt;T&gt;</a></h4>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span> <span class="k">struct</span> <span class="nc">is_tuple_like</span>
<span class="p">{</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">value</span> <span class="o">=</span> <span class="cm">/* see below */</span><span class="p">;</span>
<span class="p">};</span></code></pre>
</div>
</div>
<div class="paragraph">
<p><code>is_tuple_like&lt;T&gt;::value</code> is <code>true</code> when <code>std::tuple_size&lt;T&gt;::value</code>
is valid.</p>
</div>
<div class="paragraph">
<p>Users are allowed to specialize <code>is_tuple_like</code> for their types
if the default behavior does not deduce the correct value.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="notes"><a class="link" href="#notes">Design and Implementation Notes</a></h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="notes_quality_of_the_hash_function"><a class="link" href="#notes_quality_of_the_hash_function">Quality of the Hash Function</a></h3>
<div class="paragraph">
<p>Many hash functions strive to have little correlation between the input and
output values. They attempt to uniformally distribute the output values for
very similar inputs. This hash function makes no such attempt. In fact, for
integers, the result of the hash function is often just the input value. So
similar but different input values will often result in similar but different
output values. This means that it is not appropriate as a general hash
function. For example, a hash table may discard bits from the hash function
resulting in likely collisions, or might have poor collision resolution when
hash values are clustered together. In such cases this hash function will
perform poorly.</p>
</div>
<div class="paragraph">
<p>But the standard has no such requirement for the hash function, it just
requires that the hashes of two different values are unlikely to collide.
Containers or algorithms designed to work with the standard hash function will
have to be implemented to work well when the hash function&#8217;s output is
correlated to its input. Since they are paying that cost a higher quality hash
function would be wasteful.</p>
</div>
</div>
<div class="sect2">
<h3 id="notes_the_hash_value_customization_point"><a class="link" href="#notes_the_hash_value_customization_point">The hash_value Customization Point</a></h3>
<div class="paragraph">
<p>The way one customizes the standard <code>std::hash</code> function object for user
types is via a specialization. <code>boost::hash</code> chooses a different mechanism&#8201;&#8212;&#8201;an overload of a free function <code>hash_value</code> in the user namespace that is
found via argument-dependent lookup.</p>
</div>
<div class="paragraph">
<p>Both approaches have their pros and cons. Specializing the function object
is stricter in that it only applies to the exact type, and not to derived
or convertible types. Defining a function, on the other hand, is easier
and more convenient, as it can be done directly in the type definition as
an <code>inline</code> <code>friend</code>.</p>
</div>
<div class="paragraph">
<p>The fact that overloads can be invoked via conversions did cause issues in
an earlier iteration of the library that defined <code>hash_value</code> for all
integral types separately, including <code>bool</code>. Especially under C&#43;&#43;03,
which doesn&#8217;t have <code>explicit</code> conversion operators, some types were
convertible to <code>bool</code> to allow their being tested in e.g. <code>if</code> statements,
which caused them to hash to 0 or 1, rarely what one expects or wants.</p>
</div>
<div class="paragraph">
<p>This, however, was fixed by declaring the built-in <code>hash_value</code> overloads
to be templates constrained on e.g. <code>std::is_integral</code> or its moral
equivalent. This causes types convertible to an integral to no longer
match, avoiding the problem.</p>
</div>
</div>
<div class="sect2">
<h3 id="notes_hash_value_stability"><a class="link" href="#notes_hash_value_stability">Hash Value Stability</a></h3>
<div class="paragraph">
<p>In general, the library does not promise that the hash values will stay
the same from release to release (otherwise improvements would be
impossible). However, historically values have been quite stable. Before
release 1.81, the previous changes have been in 1.56 (a better
<code>hash_combine</code>) and 1.78 (macOS-specific change to <code>hash_combine</code>.)</p>
</div>
<div class="paragraph">
<p>Code should generally not depend on specific hash values, but for those
willing to take the risk of occasional breaks due to hash value changes,
the library now has a test that checks hash values for a number of types
against reference values (<code>test/hash_reference_values.cpp</code>),
whose <a href="https://github.com/boostorg/container_hash/commits/develop/test/hash_reference_values.cpp">version history</a>
can be used as a rough guide to when hash values have changed, and for what
types.</p>
</div>
</div>
<div class="sect2">
<h3 id="notes_hash_combine"><a class="link" href="#notes_hash_combine">hash_combine</a></h3>
<div class="paragraph">
<p>The initial implementation of the library was based on Issue 6.18 of the
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf">Library Extension Technical Report Issues List</a>
(pages 63-67) which proposed the following implementation of <code>hash_combine</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="nf">hash_combine</span><span class="p">(</span><span class="kt">size_t</span> <span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="n">v</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">seed</span> <span class="o">^=</span> <span class="n">hash_value</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">seed</span> <span class="o">&lt;&lt;</span> <span class="mi">6</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">seed</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>taken from the paper
"<a href="https://people.eng.unimelb.edu.au/jzobel/fulltext/jasist03thz.pdf">Methods for Identifying Versioned and Plagiarised Documents</a>"
by Timothy C. Hoad and Justin Zobel.</p>
</div>
<div class="paragraph">
<p>During the Boost formal review, Dave Harris pointed out that this suffers
from the so-called "zero trap"; if <code>seed</code> is initially 0, and all the
inputs are 0 (or hash to 0), <code>seed</code> remains 0 no matter how many input
values are combined.</p>
</div>
<div class="paragraph">
<p>This is an undesirable property, because it causes containers of zeroes
to have a zero hash value regardless of their sizes.</p>
</div>
<div class="paragraph">
<p>To fix this, the arbitrary constant <code>0x9e3779b9</code> (the golden ratio in a
32 bit fixed point representation) was added to the computation, yielding</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="p">&gt;</span>
<span class="kt">void</span> <span class="nf">hash_combine</span><span class="p">(</span><span class="kt">size_t</span> <span class="o">&amp;</span> <span class="n">seed</span><span class="p">,</span> <span class="n">T</span> <span class="k">const</span> <span class="o">&amp;</span> <span class="n">v</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">seed</span> <span class="o">^=</span> <span class="n">hash_value</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="o">+</span> <span class="mh">0x9e3779b9</span> <span class="o">+</span> <span class="p">(</span><span class="n">seed</span> <span class="o">&lt;&lt;</span> <span class="mi">6</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">seed</span> <span class="o">&gt;&gt;</span> <span class="mi">2</span><span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This is what shipped in Boost 1.33, the first release containing the library.</p>
</div>
<div class="paragraph">
<p>This function was a reasonable compromise between quality and speed for its
time, when the input consisted of <code>char</code>s, but it&#8217;s less suitable for
combining arbitrary <code>size_t</code> inputs.</p>
</div>
<div class="paragraph">
<p>In Boost 1.56, it was replaced by functions derived from Austin Appleby&#8217;s
<a href="https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L57-L62">MurmurHash2 hash function round</a>.</p>
</div>
<div class="paragraph">
<p>In Boost 1.81, it was changed again&#8201;&#8212;&#8201;to the equivalent of
<code>mix(seed + 0x9e3779b9 + hash_value(v))</code>, where <code>mix(x)</code> is a high quality
mixing function that is a bijection over the <code>size_t</code> values, of the form</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">k1</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="n">m1</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">k2</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="n">m2</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="n">k3</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>This type of mixing function was originally devised by Austin Appleby as
the "final mix" part of his MurmurHash3 hash function. He used</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">33</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0xff51afd7ed558ccd</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">33</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0xc4ceb9fe1a85ec53</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">33</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>as the <a href="https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash2.cpp#L57-L62">64 bit function <code>fmix64</code></a> and</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0x85ebca6b</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">13</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0xc2b2ae35</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>as the <a href="https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash3.cpp#L68-L77">32 bit function <code>fmix32</code></a>.</p>
</div>
<div class="paragraph">
<p>Several improvements of the 64 bit function have been subsequently proposed,
by <a href="https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html">David Stafford</a>,
<a href="https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html">Pelle Evensen</a>,
and <a href="http://jonkagstrom.com/mx3/mx3_rev2.html">Jon Maiga</a>. We currently use Jon
Maiga&#8217;s function</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">32</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0xe9846af9b1a615d</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">32</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0xe9846af9b1a615d</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">28</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>Under 32 bit, we use a mixing function proposed by "TheIronBorn" in a
<a href="https://github.com/skeeto/hash-prospector/issues/19">Github issue</a> in
the <a href="https://github.com/skeeto/hash-prospector">repository</a> of
<a href="https://nullprogram.com/blog/2018/07/31/">Hash Prospector</a> by Chris Wellons:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">16</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0x21f0aaad</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">15</span><span class="p">;</span>
<span class="n">x</span> <span class="o">*=</span> <span class="mh">0x735a2d97</span><span class="p">;</span>
<span class="n">x</span> <span class="o">^=</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">15</span><span class="p">;</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>With this improved <code>hash_combine</code>, <code>boost::hash</code> for strings now passes the
<a href="https://github.com/aappleby/smhasher">SMHasher test suite</a> by Austin Appleby
(for a 64 bit <code>size_t</code>).</p>
</div>
</div>
<div class="sect2">
<h3 id="notes_hash_range"><a class="link" href="#notes_hash_range">hash_range</a></h3>
<div class="paragraph">
<p>The traditional implementation of <code>hash_range(seed, first, last)</code> has been</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="rouge highlight"><code data-lang="c++"><span class="k">for</span><span class="p">(</span> <span class="p">;</span> <span class="n">first</span> <span class="o">!=</span> <span class="n">last</span><span class="p">;</span> <span class="o">++</span><span class="n">first</span> <span class="p">)</span>
<span class="p">{</span>
    <span class="n">boost</span><span class="o">::</span><span class="n">hash_combine</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">(</span> <span class="n">seed</span><span class="p">,</span> <span class="o">*</span><span class="n">first</span> <span class="p">);</span>
<span class="p">}</span></code></pre>
</div>
</div>
<div class="paragraph">
<p>(the explicit template parameter is needed to support iterators with proxy
return types such as <code>std::vector&lt;bool&gt;::iterator</code>.)</p>
</div>
<div class="paragraph">
<p>This is logical, consistent and straightforward. In the common case where
<code>typename std::iterator_traits&lt;It&gt;::value_type</code> is <code>char</code>&#8201;&#8212;&#8201;which it is
in the common case of <code>boost::hash&lt;std::string&gt;</code>&#8201;&#8212;&#8201;this however leaves a
lot of performance on the table, because processing each <code>char</code> individually
is much less efficient than processing several in bulk.</p>
</div>
<div class="paragraph">
<p>In Boost 1.81, <code>hash_range</code> was changed to process elements of type <code>char</code>,
<code>signed char</code>, <code>unsigned char</code>, <code>std::byte</code>, or <code>char8_t</code>, four of a time.
A <code>uint32_t</code> is composed from <code>first[0]</code> to <code>first[3]</code>, and that <code>uint32_t</code>
is fed to <code>hash_combine</code>.</p>
</div>
<div class="paragraph">
<p>In Boost 1.82, <code>hash_range</code> for these types was changed to use
<a href="https://github.com/pdimov/mulxp_hash"><code>mulxp1_hash</code></a>. This improves both
quality and speed of string hashing.</p>
</div>
<div class="paragraph">
<p>Note that <code>hash_range</code> has also traditionally guaranteed that the same element
sequence yields the same hash value regardless of the iterator type. This
property remains valid after the changes to <code>char</code> range hashing. <code>hash_range</code>,
applied to the <code>char</code> sequence <code>{ 'a', 'b', 'c' }</code>, results in the same value
whether the sequence comes from <code>char[3]</code>, <code>std::string</code>, <code>std::deque&lt;char&gt;</code>,
or <code>std::list&lt;char&gt;</code>.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="links"><a class="link" href="#links">Links</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p><strong>A Proposal to Add Hash Tables to the Standard Library</strong><br>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html" class="bare">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1456.html</a></p>
</div>
<div class="paragraph">
<p>The hash table proposal explains much of the design. The hash function object is discussed in Section D.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>The C&#43;&#43; Standard Library Technical Report</strong><br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf" class="bare">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf</a></p>
</div>
<div class="paragraph">
<p>Contains the hash function specification in section 6.3.2.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Library Extension Technical Report Issues List</strong><br>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf" class="bare">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1837.pdf</a></p>
</div>
<div class="paragraph">
<p>The library implements the extension described in Issue 6.18, pages 63-67.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Methods for Identifying Versioned and Plagiarised Documents</strong><br>
<em>Timothy C. Hoad, Justin Zobel</em><br>
<a href="https://people.eng.unimelb.edu.au/jzobel/fulltext/jasist03thz.pdf" class="bare">https://people.eng.unimelb.edu.au/jzobel/fulltext/jasist03thz.pdf</a></p>
</div>
<div class="paragraph">
<p>Contains the hash function that the initial implementation of <code>boost::hash_combine</code> was based on.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Performance in Practice of String Hashing Functions</strong><br>
<em>M.V. Ramakrishna, J. Zobel</em><br>
In Proc. Int. Conf. on Database Systems for Advanced Applications, pages 215-223, Melbourne, Australia, April 1997.<br>
<a href="https://www.comp.nus.edu.sg/~lingtw/dasfaa_proceedings/DASFAA97/P215.pdf" class="bare">https://www.comp.nus.edu.sg/~lingtw/dasfaa_proceedings/DASFAA97/P215.pdf</a></p>
</div>
<div class="paragraph">
<p>Referenced in the above paper as the source of the hash function.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>MurmurHash3 hash function source</strong><br>
<em>Austin Appleby</em><br>
<a href="https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash3.cpp#L65-L90" class="bare">https://github.com/aappleby/smhasher/blob/61a0530f28277f2e850bfc39600ce61d02b518de/src/MurmurHash3.cpp#L65-L90</a></p>
</div>
<div class="paragraph">
<p>Austin Appleby&#8217;s 32 and 64 bit finalization mixing functions that
introduced the "xmxmx" general form of a high quality bijective
transformation that approximates a random permutation.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>SMHasher hash function test suite</strong><br>
<em>Austin Appleby</em><br>
<a href="https://github.com/aappleby/smhasher" class="bare">https://github.com/aappleby/smhasher</a></p>
</div>
<div class="paragraph">
<p>Contains a battery of tests for evaluating hash functions. The current
64 bit implementation of <code>boost::hash</code> for strings passes SMHasher.
Previous iterations did not.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Better Bit Mixing - Improving on MurmurHash3&#8217;s 64-bit Finalizer</strong><br>
<em>David Stafford</em><br>
<a href="https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html" class="bare">https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html</a></p>
</div>
<div class="paragraph">
<p>Describes the so-called "variant 13" mixing function, an improvement
over <code>fmix64</code> from MurmurHash3, made famous by its adoption by the
<code>splitmix64</code> <a href="http://xorshift.di.unimi.it/splitmix64.c">random number generator</a>.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Stronger, better, morer, Moremur; a better Murmur3-type mixer</strong><br>
<em>Pelle Evensen</em><br>
<a href="https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html" class="bare">https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html</a></p>
</div>
<div class="paragraph">
<p>Describes Moremur, an improvement over MurmurHash3 <code>fmix64</code> and Stafford
"variant 13".</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Improved mx3 and the RRC test</strong><br>
<em>Jon Maiga</em><br>
<a href="http://jonkagstrom.com/mx3/mx3_rev2.html" class="bare">http://jonkagstrom.com/mx3/mx3_rev2.html</a></p>
</div>
<div class="paragraph">
<p>Contains another improvement over MurmurHash3 <code>fmix64</code> and "variant 13". This
is what the current implementation of <code>boost::hash_combine</code> uses when
<code>std::size_t</code> is 64 bits.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>Prospecting for Hash Functions</strong><br>
<em>Chris Wellons</em><br>
<a href="https://nullprogram.com/blog/2018/07/31/" class="bare">https://nullprogram.com/blog/2018/07/31/</a></p>
</div>
<div class="paragraph">
<p>Describes <a href="https://github.com/skeeto/hash-prospector">Hash Prospector</a>,
a utility for discovering and evaluating mixing functions.</p>
</div>
<hr>
<div class="paragraph">
<p><strong>New best known functions</strong><br>
<em>"TheIronBorn"</em><br>
<a href="https://github.com/skeeto/hash-prospector/issues/19" class="bare">https://github.com/skeeto/hash-prospector/issues/19</a></p>
</div>
<div class="paragraph">
<p>Describes a good 32 bit mixing function, used by the current implementation
of <code>boost::hash_combine</code> when <code>std::size_t</code> is 32 bits.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="thanks"><a class="link" href="#thanks">Acknowledgements</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>This library is based on the design by Peter Dimov. During the initial development Joaquín M López Muñoz made many useful suggestions and contributed fixes.</p>
</div>
<div class="paragraph">
<p>The formal review was managed by Thorsten Ottosen, and the library reviewed by: David Abrahams, Alberto Barbati, Topher Cooper, Caleb Epstein, Dave Harris, Chris Jefferson, Bronek Kozicki, John Maddock, Tobias Swinger, Jaap Suter, Rob Stewart and Pavel Vozenilek. Since then, further constructive criticism has been made by Daniel Krügler, Alexander Nasonov and 沈慧峰.</p>
</div>
<div class="paragraph">
<p>The implementation of the hash function for pointers is based on suggestions made by Alberto Barbati and Dave Harris. Dave Harris also suggested an important improvement to <code>boost::hash_combine</code> that was taken up.</p>
</div>
<div class="paragraph">
<p>Some useful improvements to the floating point hash algorithm were suggested by Daniel Krügler.</p>
</div>
<div class="paragraph">
<p>The original implementation came from Jeremy B. Maitin-Shepard&#8217;s hash table library, although this is a complete rewrite.</p>
</div>
<div class="paragraph">
<p>The documentation was converted from Quickbook to AsciiDoc by Christian Mazakas.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="changes"><a class="link" href="#changes">Change Log</a></h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="changes_boost_1_67_0"><a class="link" href="#changes_boost_1_67_0">Boost 1.67.0</a></h3>
<div class="ulist">
<ul>
<li>
<p>Moved library into its own module, <code>container_hash</code>.</p>
</li>
<li>
<p>Moved headers for new module name, now at: <code>&lt;boost/container_hash/hash.hpp&gt;</code>, <code>&lt;boost/container_hash/hash_fwd.hpp&gt;</code>, <code>&lt;boost/container_hash/extensions.hpp&gt;</code>.</p>
</li>
<li>
<p>Added forwarding headers to support the old headers locations.</p>
</li>
<li>
<p>Support <code>std::string_view</code>, <code>std::error_code</code>, <code>std::error_condition</code>, <code>std::optional</code>, <code>std::variant</code>, <code>std::monostate</code> where available.</p>
</li>
<li>
<p>Update include paths from other Boost libraries.</p>
</li>
<li>
<p>Manually write out tuple overloads, rather than using the preprocessor to generate them. Should improve usability, due to better error messages, and easier debugging.</p>
</li>
<li>
<p>Fix tutorial example (<a href="https://svn.boost.org/trac/boost/ticket/11017">#11017</a>).</p>
</li>
<li>
<p>Quick fix for hashing <code>vector&lt;bool&gt;</code> when using libc++. Will try to introduce a more general fix in the next release.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="changes_boost_1_66_0"><a class="link" href="#changes_boost_1_66_0">Boost 1.66.0</a></h3>
<div class="ulist">
<ul>
<li>
<p>Avoid float comparison warning when using Clang - this workaround was already in place for GCC, and was used when Clang pretends to be GCC, but the warning was appearing when running Clang in other contexts.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="changes_boost_1_65_0"><a class="link" href="#changes_boost_1_65_0">Boost 1.65.0</a></h3>
<div class="ulist">
<ul>
<li>
<p>Support for <code>char16_t</code>, <code>char32_t</code>, <code>u16string</code>, <code>u32string</code></p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_64_0" class="discrete">Boost 1.64.0</h3>
<div class="ulist">
<ul>
<li>
<p>Fix for recent versions of Visual C&#43;&#43; which have removed <code>std::unary_function</code> and <code>std::binary_function</code> (<a href="https://svn.boost.org/trac/boost/ticket/12353">#12353</a>).</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_63_0" class="discrete">Boost 1.63.0</h3>
<div class="ulist">
<ul>
<li>
<p>Fixed some warnings.</p>
</li>
<li>
<p>Only define hash for <code>std::wstring</code> when we know we have a <code>wchar_t</code>. Otherwise there&#8217;s a compile error as there&#8217;s no overload for hashing the characters in wide strings (<a href="https://svn.boost.org/trac/boost/ticket/8552">#8552</a>).</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_58_0" class="discrete">Boost 1.58.0</h3>
<div class="ulist">
<ul>
<li>
<p>Fixed strict aliasing violation (<a href="https://github.com/boostorg/container_hash/issues/3">GitHub #3</a>).</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_56_0" class="discrete">Boost 1.56.0</h3>
<div class="ulist">
<ul>
<li>
<p>Removed some Visual C&#43;&#43; 6 workarounds.</p>
</li>
<li>
<p>Ongoing work on improving <code>hash_combine</code>. This changes the combine function which was previously defined in the reference documentation.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_55_0" class="discrete">Boost 1.55.0</h3>
<div class="ulist">
<ul>
<li>
<p>Simplify a SFINAE check so that it will hopefully work on Sun 5.9 (<a href="https://svn.boost.org/trac10/ticket/8822">#8822</a>).</p>
</li>
<li>
<p>Suppress Visual C&#43;&#43; infinite loop warning (<a href="https://svn.boost.org/trac10/ticket/8568">#8568</a>).</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_54_0" class="discrete">Boost 1.54.0</h3>
<div class="ulist">
<ul>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/7957">Ticket 7957</a>: Fixed a typo.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_53_0" class="discrete">Boost 1.53.0</h3>
<div class="ulist">
<ul>
<li>
<p>Add support for <code>boost::int128_type</code> and <code>boost::uint128_type</code> where available - currently only <code>__int128</code> and <code>unsigned __int128</code> on some versions of gcc.</p>
</li>
<li>
<p>On platforms that are known to have the standard floating point functions, don&#8217;t use automatic detection - which can break if there are ambiguous overloads.</p>
</li>
<li>
<p>Fix undefined behaviour when using the binary <code>float</code> hash (Thomas Heller).</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_52_0" class="discrete">Boost 1.52.0</h3>
<div class="ulist">
<ul>
<li>
<p>Restore <code>enum</code> support, which was accidentally removed in the last version.</p>
</li>
<li>
<p>New floating point hasher - will hash the binary representation on more platforms, which should be faster.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_51_0" class="discrete">Boost 1.51.0</h3>
<div class="ulist">
<ul>
<li>
<p>Support the standard smart pointers.</p>
</li>
<li>
<p><code>hash_value</code> now implemented using SFINAE to avoid implicit casts to built in types when calling it.</p>
</li>
<li>
<p>Updated to use the new config macros.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_50_0" class="discrete">Boost 1.50.0</h3>
<div class="ulist">
<ul>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/6771">Ticket 6771</a>: Avoid gcc&#8217;s <code>-Wfloat-equal</code> warning.</p>
</li>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/6806">Ticket 6806</a>: Support <code>std::array</code> and <code>std::tuple</code> when available.</p>
</li>
<li>
<p>Add deprecation warning to the long deprecated <code>boost/container_hash/detail/container_fwd.hpp</code>.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_46_0" class="discrete">Boost 1.46.0</h3>
<div class="ulist">
<ul>
<li>
<p>Avoid warning due with gcc&#8217;s <code>-Wconversion</code> flag.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_44_0" class="discrete">Boost 1.44.0</h3>
<div class="ulist">
<ul>
<li>
<p>Add option to prevent implicit conversions when calling <code>hash_value</code> by defining <code>BOOST_HASH_NO_IMPLICIT_CASTS</code>. When using <code>boost::hash</code> for a type that does not have <code>hash_value</code> declared but does have an implicit conversion to a type that does, it would use that implicit conversion to hash it. Which can sometimes go very wrong, e.g. using a conversion to <code>bool</code> and only hashing to 2 possible values. Since fixing this is a breaking change and was only approached quite late in the release cycle with little discussion it&#8217;s opt-in for now. This, or something like it, will become the default in a future version.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_43_0" class="discrete">Boost 1.43.0</h3>
<div class="ulist">
<ul>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/3866">Ticket 3866</a>: Don&#8217;t foward declare containers when using gcc&#8217;s parallel library, allow user to stop forward declaration by defining the <code>BOOST_DETAIL_NO_CONTAINER_FWD</code> macro.</p>
</li>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/4038">Ticket 4038</a>: Avoid hashing <code>0.5</code> and <code>0</code> to the same number.</p>
</li>
<li>
<p>Stop using deprecated <code>BOOST_HAS_*</code> macros.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_42_0" class="discrete">Boost 1.42.0</h3>
<div class="ulist">
<ul>
<li>
<p>Reduce the number of warnings for Visual C&#43;&#43; warning level 4.</p>
</li>
<li>
<p>Some code formatting changes to fit lines into 80 characters.</p>
</li>
<li>
<p>Rename an internal namespace.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_40_0" class="discrete">Boost 1.40.0</h3>
<div class="ulist">
<ul>
<li>
<p>Automatically configure the <code>float</code> functions using template metaprogramming instead of trying to configure every possibility manually.</p>
</li>
<li>
<p>Workaround for when STLport doesn&#8217;t support long double.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_39_0" class="discrete">Boost 1.39.0</h3>
<div class="ulist">
<ul>
<li>
<p>Move the <code>hash_fwd.hpp</code> implementation into the hash subdirectory, leaving a forwarding header in the old location. You should still use the old location, the new location is mainly for implementation and possible modularization.</p>
</li>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/2412">Ticket 2412</a>: Removed deprecated headers.</p>
</li>
<li>
<p><a href="https://svn.boost.org/trac/boost/ticket/2957">Ticket 2957</a>: Fix configuration for vxworks.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_38_0" class="discrete">Boost 1.38.0</h3>
<div class="ulist">
<ul>
<li>
<p>Changed the warnings in the deprecated headers from 1.34.0 to errors. These will be removed in a future version of Boost.</p>
</li>
<li>
<p>Moved detail headers out of <code>boost/container_hash/detail</code>, since they are part of <code>functional/hash</code>, not <code>container_hash</code>. <code>boost/container_hash/detail/container_fwd.hpp</code> has been moved to <code>boost/detail/container_fwd.hpp</code> as it&#8217;s used outside of this library, the others have been moved to <code>boost/functional/hash/detail</code>.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_37_0" class="discrete">Boost 1.37.0</h3>
<div class="ulist">
<ul>
<li>
<p><a href="http://svn.boost.org/trac/boost/ticket/2264">Ticket 2264</a>: In Visual C&#43;&#43;, always use C99 float functions for long double and float as the C&#43;&#43; overloads aren&#8217;t always availables.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_36_0" class="discrete">Boost 1.36.0</h3>
<div class="ulist">
<ul>
<li>
<p>Stop using OpenBSD&#8217;s dodgy <code>std::numeric_limits</code>.</p>
</li>
<li>
<p>Using the boost typedefs for <code>long long</code> and <code>unsigned long long</code>.</p>
</li>
<li>
<p>Move the extensions into their own header.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_35_0" class="discrete">Boost 1.35.0</h3>
<div class="ulist">
<ul>
<li>
<p>Support for <code>long long</code>, <code>std::complex</code>.</p>
</li>
<li>
<p>Improved algorithm for hashing floating point numbers:</p>
<div class="ulist">
<ul>
<li>
<p>Improved portablity, as described by Daniel Krügler in <a href="http://lists.boost.org/boost-users/2005/08/13418.php">a post to the boost users list</a>.</p>
</li>
<li>
<p>Fits more information into each combine loop, which can reduce the the number of times combine is called and hopefully give a better quality hash function.</p>
</li>
<li>
<p>Improved the algorithm for hashing floating point numbers.</p>
</li>
<li>
<p>On Cygwin use a binary hash function for floating point numbers, as Cygwin doesn&#8217;t have decent floating point functions for <code>long double</code>.</p>
</li>
<li>
<p>Never uses <code>fpclass</code> which doesn&#8217;t support <code>long double</code>.</p>
</li>
<li>
<p><a href="http://svn.boost.org/trac/boost/ticket/1064">Ticket 1064</a>: Removed unnecessary use of errno.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Explicitly overload for more built in types.</p>
</li>
<li>
<p>Minor improvements to the documentation.</p>
</li>
<li>
<p>A few bug and warning fixes:</p>
<div class="ulist">
<ul>
<li>
<p><a href="http://svn.boost.org/trac/boost/ticket/1509">Ticket 1509</a>: Suppress another Visual C&#43;&#43; warning.</p>
</li>
<li>
<p>Some workarounds for the Sun compilers.</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
<h3 id="changes_boost_1_34_1" class="discrete">Boost 1.34.1</h3>
<div class="ulist">
<ul>
<li>
<p><a href="https://svn.boost.org/trac10/ticket/952">Ticket 952</a>: Suppress incorrect 64-bit warning on Visual C&#43;&#43;.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_34_0" class="discrete">Boost 1.34.0</h3>
<div class="ulist">
<ul>
<li>
<p>Use declarations for standard classes, so that the library doesn&#8217;t need to include all of their headers</p>
</li>
<li>
<p>Deprecated the <code>&lt;boost/functional/hash/*.hpp&gt;</code> headers. Now a single header, <code>&lt;boost/functional/hash.hpp&gt;</code> is used.</p>
</li>
<li>
<p>Add support for the <code>BOOST_HASH_NO_EXTENSIONS</code> macro, which disables the extensions to TR1.</p>
</li>
<li>
<p>Minor improvements to the hash functions for floating point numbers.</p>
</li>
<li>
<p>Update the portable example to hopefully be more generally portable.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_33_1" class="discrete">Boost 1.33.1</h3>
<div class="ulist">
<ul>
<li>
<p>Fixed the points example, as pointed out by 沈慧峰.</p>
</li>
</ul>
</div>
<h3 id="changes_boost_1_33_0" class="discrete">Boost 1.33.0</h3>
<div class="ulist">
<ul>
<li>
<p>Initial Release</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="copyright"><a class="link" href="#copyright">Copyright and License</a></h2>
<div class="sectionbody">
<div class="paragraph">
<p>This documentation is</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Copyright 2005-2008 Daniel James</p>
</li>
<li>
<p>Copyright 2022 Peter Dimov</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>and is distributed under the <a href="http://www.boost.org/LICENSE_1_0.txt">Boost Software License, Version 1.0</a>.</p>
</div>
</div>
</div>
</div>
</body>
</html>